#include <fstream>
#include <boost/date_time/posix_time/posix_time.hpp>

#include <fastcgi++/request.hpp>
#include <fastcgi++/manager.hpp>

#include "ServerContext.h"

#include "TestHandler.h"
#include "AdUrlHandler.h"
#include "DbUtil.h"

#include <my_global.h>
#include <mysql.h>
#include <stdio.h>
#include <time.h>

#include "DBPool.h"

//#include "RedisConnetionPool.h"

#include "IniFile.h"

#include "RapidJsonMacro.h"

#include <spnetkit/spnkhttpcli.hpp>
#include <spnetkit/spnkhttpmsg.hpp>
#include <spnetkit/spnkporting.hpp>
#include <spnetkit/spnksocket.hpp>

#include "util.h"

static char *opt_host_name = "192.168.1.230";        /*服务器主机名称 默认为localhost*/
static char *opt_user_name = "root";        /*数据库用户名 默认为当前登录名*/
static char *opt_password = "root";        /*密码 默认为空*/
static uint opt_port_num = 0;            /*端口 使用内建值*/
static char *opt_socket_name = NULL;    /*socket name (use build-in value)*/
static char *opt_db_name = "ad";        /*数据库 名称 默认为空*/
static uint opt_flags = 0;                /*连接参数*/

static MYSQL *conn;                        /*pointer to connection handler*/

void print_error(MYSQL *conn, const char *title){
    fprintf(stderr,"%s:\nError %u (%s)\n",title,mysql_errno(conn),mysql_error(conn));
}

void process_result_set(MYSQL *conn,MYSQL_RES *res_set){
    MYSQL_ROW row;
    uint i;

    while ((row = mysql_fetch_row(res_set)) != NULL){
        for(i=0;i<mysql_num_fields(res_set);i++){
            if (i > 0)
                fputc('\t',stdout);
            printf("%s",row[i] != NULL ? row[i] : "NULL");
        }
        fputc('\n',stdout);
    }

    if(mysql_errno(conn) != 0)
        print_error(conn,"mysql_fetch_row() failed");
    else
        printf("%lu rows returned \n",
            (ulong)mysql_num_rows(res_set));
}

using namespace std;

#if 0
void test1(){
    Context* ctx = ServerContext::getInstance();
    CConnectionPool* pool = static_cast<CConnectionPool*>(ctx->getContext("ad"));

    std::string sql = "select id,url,image_url,type,validate,add_time,due_time from tb_ad_url \
            where type=1 and validate=1";

    clock_t start, finish;
    start = clock();
    cout<<start<<std::endl;

    int i;
    int cnt = 10000;

    for(i=0;i<cnt;i++){
        mysqlpp::StoreQueryResult res = DbUtil::Select(pool,sql);

        // if(res){
        // 	for (size_t i = 0; i < res.num_rows(); ++i){
        // 		cout << res[i][1]<<std::endl;
        // 	}
        // }
    }

    finish = clock();
    cout<<finish<<std::endl;

    cout<<double (finish-start) <<std::endl;
}
#endif

void test2(){
    /*初始化数据库指针*/
    if( (conn = mysql_init(NULL))== NULL){
        fprintf(stderr,"mysql 初始化失败(可能是内存溢出)!\n");
        exit(1);
    }
    /*连接到数据库*/
    if(mysql_real_connect(conn,opt_host_name,opt_user_name,opt_password,
        opt_db_name,opt_port_num,opt_socket_name,opt_flags) == NULL){

            fprintf(stderr,"mysql_real_connect 失败:\nError %u (%s)\n",
                mysql_errno(conn),mysql_error(conn));

            mysql_close(conn);
            exit(1);
    }

    int i;
    int cnt = 10000;

    clock_t start, finish;
    start = clock();
    cout<<start<<std::endl;

    for(i=0;i<cnt;i++){

        /*查询*/
        if(mysql_query(conn,"select id,url,image_url,type,validate,add_time,due_time from tb_ad_url \ "
                       "where type=1 and validate=1")){
            print_error(conn,"mysql_query() error");

        }else{
            MYSQL_RES *res_set;
            res_set = mysql_store_result(conn);    /*生成结果集*/
            if(res_set == NULL)
                print_error(conn,"mysql_store_result failed");
            else {
                // process_result_set(conn,res_set);
                mysql_free_result(res_set);
            }
        }

    }

    finish = clock();
    cout<<finish<<std::endl;

    cout<<double (finish-start) <<std::endl;

    /*断开*/
    mysql_close(conn);

}

void test3() {
    Context* ctx = ServerContext::getInstance();
    CDBPool* dbpool = static_cast<CDBPool*>(ctx->getContext("dbpool_ad"));

    std::string sql = "select id,url,image_url,type,validate,add_time,due_time from tb_ad_url \
            where type=1 and validate=1";

    CDBConn* conn = dbpool->GetDBConn();

    int i;
    int cnt = 10000;

    clock_t start, finish;
    start = clock();
    cout<<start<<std::endl;

    for(i=0;i<cnt;i++){
        CResultSet* res = conn->ExecuteQuery(sql.c_str());

        // while(res->Next()){
        // 	std::cout<<res->GetString("url")<<std::endl;
        // }
    }

    finish = clock();
    cout<<finish<<std::endl;

    cout<<double (finish-start) <<std::endl;

}
#if 0
void test4() {
    Context* ctx = ServerContext::getInstance();
    CacheConnectionPool* redisPool = static_cast<CacheConnectionPool*>(ctx->getContext("redisPool"));

    CacheConnection* conn = redisPool->getCacheConnection();

    std::string value;

    if(conn->get("test",value)) {
        cout<<value<<endl;
    }

    int i;
    int count = 100;

    time_t t1,t2;

    time(&t1);

    for(i=0;i<count;i++) {
        conn->get("test",value);
    }

    time(&t2);

    cout<<t2-t1<<endl;

    redisPool->putCacheConnection(conn);
}
#endif

void test5() {
    char json[] = "{\"name\":\"test\",\"age\":13,\"email\":\"actest@163.com\",\"child\":{\"node1\":\"value1\",\"node2\":\"value2\"} }";

    rapidjson::Document d;

    d.Parse<0>(json);

    cout<<d["name"].GetString()<<endl;
    if(d.HasMember("name111")) {
        cout<<d["name11"].GetString()<<endl;
    }

    cout<<d["age"].GetInt()<<endl;

    if (d.IsObject() && d.HasMember("child")) {
        const rapidjson::Value& child = d["child"];

        if (child.IsObject() && child.HasMember("node1")) {
            cout<<"node1 value1="<<child["node1"].GetString()<<endl;
        }
    }
}


void test6() {
    vector<CIniFile::Record> content;

    string ip,port,database,auth;

    ip = CIniFile::GetValue("ip","Database","test.ini");
    port = CIniFile::GetValue("port","Database","test.ini");
    database = CIniFile::GetValue("db","Database","test.ini");
    cout<<ip<<" "<<port<<" "<<database<<endl;

    ip = CIniFile::GetValue("ip","redis","test.ini");
    port = CIniFile::GetValue("port","redis","test.ini");
    auth = CIniFile::GetValue("auth","redis","test.ini");
    cout<<ip<<" "<<port<<" "<<auth<<endl;

}

void test7() {
    rapidjson::Document d;
    rapidjson::Document::AllocatorType& allocate = d.GetAllocator();

    rapidjson::Value object(rapidjson::kObjectType);

    int i;
    for(i=0;i<3;i++) {
        object.AddMember("id",i,allocate);
    }

    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);

    object.Accept(writer);

    std::string ret = buffer.GetString();
    cout<<ret<<endl;

    ///////////////////////////////////////////////////////////////////////////

    rapidjson::Value array(rapidjson::kArrayType);

    for (i=0;i<3;i++) {
        rapidjson::Value obj(rapidjson::kObjectType);

        obj.AddMember("name","test1",allocate);
        obj.AddMember("age",10,allocate);
        obj.AddMember("email","test@test.com",allocate);

//        obj.SetInt(i);

        array.PushBack(obj,allocate);
    }

    rapidjson::Document doc;

    doc.SetObject();

    doc.AddMember("user",array,allocate);

    rapidjson::StringBuffer buf;
    rapidjson::Writer<rapidjson::StringBuffer> w(buf);

    doc.Accept(w);

    std::string out = buf.GetString();

    cout<<out<<endl;


}

void test8() {
    spnk_initsock();

    SP_NKHttpRequest request;

    request.setURI("/");
//    request.addParam("id","174487");
    request.setMethod("GET");
    request.setVersion("HTTP/1.1");
    request.addHeader("Connection","Keep-Alive");
    request.addHeader("Host","www.jw9888.com");

    char ip[32];

    if(dns("www.jw9888.com",ip,sizeof(ip)) != 0) {
        return ;
    }

    SP_NKTcpSocket sp_socket(ip,1688);
//    SP_NKTcpSocket sp_socket("www.jw9888.com",1688);

    SP_NKHttpResponse response;

    int ret = SP_NKHttpProtocol::get(&sp_socket,&request,&response);

    if(ret == 0) {
        cout<<"request successfully!"<<endl;

        if(response.getContent() && response.getContentLength() > 0) {
            cout<<"response:"<<(char *)response.getContent()<<endl;
        }
    }else {
        cout<<"request fail!"<<endl;
    }

}

void test9() {
    rapidjson::Document d;
    rapidjson::Value object(rapidjson::kObjectType);

    const char* p1 = "test4",*v1 = "value4";
    const char* p2 = "test5",*v2 = "value5";

    rapidjson::Value o(rapidjson::kObjectType);
    RapidJsonObjAddMember(d,o,"obj1","value1");
    RapidJsonObjAddMember(d,o,"obj2","value2");

    o.AddMember("test",1,d.GetAllocator());

    RapidJsonObjAddMember(d,o,"1000",1000);

//    RapidJsonObjAddStrMember(d,o,p1,p2);
    std::string s1 = "teststr";
//    o.AddMember(s1.c_str(),v1,d.GetAllocator());
    RapidJsonObjAddStrMember(d,o,s1.c_str(),v1);

    RapidJsonObjAddMember(d,object,"child",o);

    std::string str;

    RapidJsonGetString(object,str);

    cout<<str<<endl;
}

void test10(){
    uuid_t u = uuid();
    cout<<u<<endl;
}

int main()
{

    ///////////////////////////////////////////////////////////////////////////
    ///环境上下文创建
    ///////////////////////////////////////////////////////////////////////////
    Context* ctx = ServerContext::getInstance();

#if 0
    CConnectionPool* pool1 = new CConnectionPool("192.168.1.106",3306,"caipiao","root","root");
    CConnectionPool* pool2 = new CConnectionPool("192.168.1.106",3306,"ad","root","root");

    CDBPool* dbpool1 = new CDBPool("ad","192.168.1.106",3306,"root","root","ad",100000);
    dbpool1->Init();
#endif

//    CacheConnectionPool* redisPool = new RedisConnectionPool("192.168.1.240",6379,"mygod");

#if 0
    ctx->setContext("caipiao",static_cast<void*>(pool1) );
    ctx->setContext("ad",static_cast<void*>(pool2) );

    ctx->setContext("dbpool_ad",static_cast<void*>(dbpool1) );
#endif

//    ctx->setContext("redisPool",static_cast<void*>(redisPool));

    ///////////////////////////////////////////////////////////////////////////
    ///执行测试
    ///////////////////////////////////////////////////////////////////////////

    // test1();
    // test2();
//    test3();
//    test4();
//    test5();
//    test6();

//    test7();
//    test8();
//    test9();
    test10();

    ///////////////////////////////////////////////////////////////////////////
}
